<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html;charset=utf-8">
        <title> Multitasking the Android Way </title>
        <link rel="stylesheet" type="text/css" href="print.css" />
    </head>
    
    <body>
      <h1>Multitasking the Android Way</h1>
      <div>
        android在允许多个应用同时运行的方式是非常独特的。来自其它平台的开发者将发现这种方式非常独特。
        理解它的行为将有利于将程序设计得运行得更好，和与android平台无缝集成。这篇文章讲解了android多任务设计的缘由;和它对程序如何运行的影响，以及如果最大限度的利用android的特性。
      </div>
      <div>
        <h2>Design considerations</h2>
        <p>
            手机设备有技术限制，同时用户体验也不同于web系统及桌面应用。下面是在我们设计android多任务时四个关键的限制:
        </p>
        <ul>
            <li> 当用户使用完应用时我们不需要用户去关闭它。这样一个模式在一个用户整天不同的与各种不同的应用打交道的环境。</li>
             <li>手机设备没有很大的交换空间，因此在内存使用的限制上有硬性的限制。Robert Love在这个方面有一篇很好的文章(http://blog.rlove.org/2010/04/why-ipad-and-iphone-dont-support.html) </li>
              <li> 应用程序在手机设备上的切换是有很极端的限制的;我们的目标是在1秒内启动一个新的应用。当用户只在几个应用之间切换时，这一点特别重要，例如如果用户在看视频的时候切换去看一条新短信，然后返回继续看视频。如果在这种情况下等待比较久的话，将会很快使用户不满。 </li>
               <li> 这些可用的api要能够很高效的用于写内置的Google应用，作为我们"所有应用都是平等创建“的原则。
        这意味着后台运行的音乐，数据同步，GPS导航，和应用下载都是通过同样的即第三方开发者可用的API来实现 </li>
        </ul>
        <p>
            上面的头两条需求突出了一个效益冲突。我们并不想用户去担心关闭他们的应用，但是却看它看起来所有的应用都是一直在运行。同时，手机设备可用内存有限，因此系统将退化并开始衰减当内在供不就求的时候;而一个桌面电脑，有交换分区，反过来说，当需要在交换空间进行内存时分页时，它将变慢。这个相互矛盾的限制是anroid设计的关键动机。
        </p>
      </div>
	  
	  <div>
		<h2>When  does an application "stop"?</h2>
		<p>
			一个关于android多线程通常的误解是关于一个进程与一个应用的区别.
			在android中它们并不是一个紧密耦合的实体:对于用户应用看起来没有一个实际的进程在运行此应用;
			多个应用可以共享进程,或者一个应用根据它的需要使用多个进程;甚至当一个应用没有在什么事情时应用的进程也一直在android中存在.
			实际上你可以看到一个应用进程的运行并不意味着这个应用正在运行或者做什么事.它只是就在哪里而已,因为也许android会在某个时候需要它,
			或者因为最好是保存它以便它再次使用.同理,你也许会离开一个应用,然后又返回刚才离开的地方,在你离开的时候,android也许会因为某些
			事件丢弃这个线程.
		</p>
		<p>
			了解android应用处理应用程序的关键是应用并没有关闭之后并没有完全的清理,当用户离开一个应用的时候,它的进程也许会保存在后台中,
			以便需要的话再次工作(例如,下载网页), 同时在用户需要的时候马上回到前台.如果设备不会内存溢出,那android将保存所有这些进程,看起来这些进程都是一直在运行.
		</p>
		<p>
			当然,内存是有限的,为了达到此目的,android必需决定什么时候清理不需要的线程.这就是android进程生命周期的来历.
,用户判断进程重要性的规则,因此次要的将关闭.这条规则中重要性基于两点,一是进程对于当前用户体验的重要性,二是它距离上次被用户使用多久了.

		</p>
		<p>
			一旦android决定关闭一个进程,它会很暴力的仅仅是杀掉它.内核将立即释放此进程占用的资源,而不是给进程一个礼貌的退出请求再等到它响应.
			这种机制有利于方便的避免更严重的内存溢出问题.
		</p>
		<p>
			如果用户再次返回到已经被杀死的应用中,Android需要一种能够重新启动应用到杀死前的状态,
			保留"所有的应用仿佛都是在同时运行"的体验.这是通过保存用户注意到的应用,并且在重新启动应用的时候,
			恢复用户最后看到的状态.这些最后的状态是当用户离开这些应用时保存,而不是被杀死时,因此内核在稍后能够轻松的杀死进程
			而不用担心应用能够在那一点上是否能正确响应.
		</p>
		<p>
			在某种意义来说,android的进程管理也可以看作一种交换空间的形式:
			应用进程代表一定数量使用的内存,当内存不够时,一些进程被杀死(被交换出);当再次需要这些进程时,他们能够用它们最后的状态重新启动(交换进).
		</p>
	  </div>
	  
	  <div>
		<h2>Explicitly running in the background</h2>
		<p>
			到目前为止,我们有一种让应用在后台隐式工作的方式--只要这个应用没有被android在常规内存管理中杀死.
			这对于在后台加载网页来说足够了,但是如果应付刚性的需要呢?如后台播放音乐,数据同步,定位,闹钟等等.
		</p>
		<p>
			对于这些任务,这些应用需要以某种方式来告诉android说"我想要在后台运行",对于此,应用有两种主要的设施可用,
			即可以在manifest中声明的两种组件:<code>broadcast receivers</code>和<code>services</code>
		</p>
		<div>
			<h3>Broadcast Receivers</h3>
			<p>
			当某些事情发生时,一个BroadcastReceiver可以让一个应用在后台运行一小段时间.
			它可以用来构建更高级的基础设施;例如<code>AlarmManager</code>允许一个应用去在某个时间发送一个广播(broadcast
			,一个<code>LocationManager</code>在检测到位置上有意义的改变时发送一个广播.因为关于<code>receiver</code>的信息是应用
			清单的一部分. 所以android能够找到并启动这个应用就算它并没有在运行;当然如果它已经有一个进程在后台可用,那么广播将
			很快地直接转发到进程中去.
			</p>
			<p>
				当处理一个广播(broadcast)时,系统给应用分配了一个固定的时间(现在是10秒)用于应用的操作.如果它在哪个时间没有完成操作,
				此应用将被认为是有异常操作的,它的进程将被打进后台状态并且如果在需要内存的时候被杀死.
			</p>
			<p>
				广播接收者(Broadcast receivers)非常适合在一些外部条件触发时做一些简单的片段操作,例如当新的GPS位置设定时向用户
				投递一个新的通知.它们是非常轻量的,因为这个应用的进程只需要在接收到广播的时候进行些操作.因为他们只运行一定的时间,而且有很可靠的保证在运行时不被杀死.
				然而他们不适合进行任何不知道时间的操作,例如网络操作.
			</p>
		</div>
		
		<div>
			<h3>Services</h3>
			<p>
			一个服务(Service)允许一个应用在后台长期运行的操作.实际上service还能够提供很多其它的功能,但是在这里的讨论
			基于这样的一个基本目的---应用需要在后台持续运行,直到操作完成.一个应用可以通过显式的启动和停止service来控制它.
			</p>
			<p>
				然而service没有提供一个富C/S模型,它的使用是可选的.在启动一个应用的service的时候,android只是简单的在进程中实例化
				这个组件来提供其context.然而他稍后的使用取决于应用;它能在一个服务中放置所需要的代码而不用去跟应用的其它部分交互,
				在与其它应用部分共享的单例对象中进行调用,直接在需要的地方取得<code>Service</code>的实例.如果需要的话可以通过一个
				RPC协议来在其它进程中运行.	
			</p>
			<p>
				对于服务的进程管理不同于broadcast receiver(广播接收者),因为任意的服务可以请求运行任意长的时间.
				有可能没有足够的内存来满足所有请求运行的服务,结果,并不能保证他们能够一直运行.
			</p>
			<p>
				如果只有一点内存,进程中的服务将会向后台进程一新被马上杀死.但是,如果可能的话android会知道哪些服务
				还希望继续运行,当有足够的内存可用的时候,系统将自动重新它们.例如,如果用户浏览一个网页,这需要很大的内存,
				android会结束后台的如同步进程,直到浏览器内存使用降低.
			</p>
			<p>
			 服务可以通过与android系统协商将自己作为一个"前台"进程以改变这种默认的行为.这将会使service处于一种"请别结束我"
			 的状态,但是需要通知用户依然在运行.对于后台音乐播放或者车载导航等service这很有用,用户将清楚的知道他们正在运行.
			 当你在播放音乐时同时浏览网页,你能够在状态条中看到正在播放的曲目,android不会杀掉这些服务,但是作为一个默认的约定,
			 确保用户知道他们,并且在需要的时候能够显式的关闭他们.
			</p>
		</div>
		
		<div>
			<h3>The value of generic components</h3>
			<p>
			    android的通用broadcast receiver（广播接收者）及service组件能够让开发者创建丰富多样的高效后台操作，包含开发者原来从来没有想到过的。在android1.0中，他们用于实现几乎内置的及Google App提供的所有应用的后台操作:
			    <ul>
			        <li>允许用户离开音乐应用后音乐播放还在一个服务中运行。</li>
			        <li>闹钟用一个闹钟管理者调度广播接收者，以达到在下次设定的闹钟时刻响起。</li>
			        <li>日历应用同样调度了一个闹钟在下一个日历事件中适当的时候来显示或者更新通知</li>
			        <li>后台文件下载以一个服务来实现，当有下载来处理时</li>
			        <li>E-mail应用也在使用了闹钟调度来在一个以一个固定的时间频率来检查并取回新邮件。</li>
			        <li>Google的应维护了一个从网络推送通知的服务;它还会向单独的应用依次发出广播当它们需要去做如同步联系人的事件时。</li>
			    </ul>
			 </p>
			 
			 <p>
			    随着平台的演变，这些基本的组件用来实现更多主要的开发特性:
			    <ul>
			        <li>开发者用Service来实现输入法，android管理服务作为当前的输入法</li>
			        <li>窗口小部件(Application widget）是广播接收者，当需要与它们交互时，android向它们发送广播。这让窗口小部件变得很轻量，不需要它们的应用还一直在运行。</li>
			        <li>附近功能作为一个服务来实现，android让它一直运行着，同时发送与用户交互相关的信息。</li>  <li>
			        在android2.0中推出的Sync adapter（同步适配器),作为一个运行在后台的服务-当某一些数据需要同步时，
			        </li>
			        <li>当一个动态壁纸被用户选择时，android将它作为一个服务在后台启动。</li>
			    </ul>
			 </p>
			
		</div>
		
	  </div>
    </body>
</html>




























